#!/bin/sh
exec scala "$0" "$@"
!#

import java.io.File
import java.io.PrintWriter
import java.util.Scanner
import java.util.regex.Pattern
import java.util.regex.Matcher
import java.util.Date
import java.text.DateFormat

object Sibuti {

	/**
	 *	Replaces ä:s with &auml;s etc. in given String and returns it
	 */
	def replaceScands(t: String): String = {
		var s = t
		s = s.replace("ä", "&auml;")
		s = s.replace("ö", "&ouml;")
		s = s.replace("Ä", "&Auml;")
		s = s.replace("Ö", "&Ouml;")
		return s
	}

	/**
	 *	orderByTime orders the printing of files in fs in the order of latest to oldest
	 */
	def orderByTime(fs: List[File]): List[File] = {

		if (fs.length > 1) {
			var latest = fs(0)
			for (i <- 1 to fs.length-1) { // go through fs, find latest
				if (latest.lastModified() < fs(i).lastModified()) {
					latest = fs(i)
				}
			}

			// create new list of files, latest removed
			var newfs = List[File]()
			for (a <- fs) {
				if (a != latest) {
					newfs = a :: newfs
				}
			}
			println("adding " + latest.getName())
			latest :: orderByTime(newfs)
		}

		else {	// only one file (left)? return it!
			if (fs.length == 1) println("adding " + fs(0).getName())
			fs
		}
	}

	def getTitle(cfg: File): String = {
		val cfgreader = new Scanner(cfg)
		var tf = false	// tf for title found
		val titlePattern = getPattern("title")
		var title = "Blog title"
		while (cfgreader.hasNextLine() && !tf) {
			val line = cfgreader.nextLine()
			val m = titlePattern.matcher(line)
			if (m.matches()) {
				title = m.group(2)
				(tf = false)
			}
		}

		title
	}

	def getValidFiles(txtFolder: File): List[File] = {
		// invalid files
		val wrongFiles = Pattern.compile(".*~{1}|.*(\\.)+.*")

		// valid files (exception to the above)
		val txtFiles = Pattern.compile(".*\\.{1}txt")

		var validfs = List[File]()	// list of VALID files
		for (a <- txtFolder.listFiles()) {
			if (!wrongFiles.matcher(a.getName()).matches() || txtFiles.matcher(a.getName()).matches()) { // && txtFiles.matcher(a.getName()).matches()) {
				validfs = a :: validfs
			}
		}
		validfs
	}

	def getPattern(s: String): Pattern = {
		Pattern.compile("(?:(" + s + ":))(?>(.*$))")
	}

	def createStylesheet(ssname: String, cfgFile: File): String = {

		// all parameters initiated with default values
		var bgcolor = "white"
		var txtcolor = "black"
		var tablebgcolor = "white"
		var font = "Book Antiqua"

		// patterns for searching each value
		val bgcolorPattern = getPattern("background")
		val txtcolorPattern = getPattern("text color")
		val tablebgPattern = getPattern("table bg")
		val fontPattern = getPattern("font")

		val cfgsc = new Scanner(cfgFile)
		while (cfgsc.hasNextLine()) {
			val line = cfgsc.nextLine()

			val m = bgcolorPattern.matcher(line)
			val n = txtcolorPattern.matcher(line)
			val o = tablebgPattern.matcher(line)
			val p = fontPattern.matcher(line)

			if (m.matches()) bgcolor = m.group(2).trim()
			else if (n.matches()) txtcolor = n.group(2).trim()
			else if (o.matches()) tablebgcolor = o.group(2).trim()
			else if (p.matches()) font = p.group(2).trim()
		}
		cfgsc.close()

		// create stylesheet!
		var stylesheet = new File(ssname)
		val out = new PrintWriter(stylesheet)

		// BODY tag for background color
		out.write("BODY {\nbackground-color: " + bgcolor + ";\n}\n\n")

		// H1 tag
		out.write("H1 {\ntext-align: center;\nmargin-top: 1em;\nmargin-bottom: 1em;\nborder: solid;\n}\n\n")

		// H2 tag
		out.write("H2 {\ntext-align: center;\nmargin-top: 0.5em;\nmargin-bottom: 1em;\n}\n\n")

		// H3 tag
		out.write("H3 {\ntext-align: left;\nmargin-top: 0.5em;\nmargin-bottom: 1em;\n}\n\n")

		// P tag
		out.write("P {\nmargin-top: 1em;\nmargin-bottom: 1em;\ntext-align: justify;\ntext-indent: 2em;\nfont-family: \"" + font + "\", Palatino, sans-serif;\ncolor: " + txtcolor + ";\n}\n\n")

		// (P).timestamp tag
		out.write(".timestamp {\ntext-align: right;\nfont-style: italic;\ntext-indent: 0em;\n}\n\n")

		// (P).dots tag, a little trick to separate entries
		out.write(".dots {\nborder-style: double;\nborder-width: 5px;\n")
		out.write("border-color: " + txtcolor + " " + tablebgcolor + " " + tablebgcolor + " " + tablebgcolor + ";\n")
		out.write("text-align: center;\nwidth: 10%;\nfont-size: 1px;\n}\n\n")

		// TABLE tag
		out.write("TABLE {\nmargin-top: 1em;\nmargin-bottom: 0em;\nwidth: 30.0em;\nmargin-left: auto;\nmargin-right: auto;\nborder-style: none;\nbackground-color: " + tablebgcolor + ";\npadding: 1.9em;\n}\n\n")

		// always remember these with PrintWriter
		out.flush()
		out.close()

		"hello"
	}

	def main(args: Array[String]) = {

		// create index.html
		val f = new File("index.html")
		val out = new PrintWriter(f)

		// open cfg file
		val cfg = new File("cfg")
		val title = getTitle(cfg)
		createStylesheet("stylesheet.css", cfg)

		// print head
		out.write("<HTML>\n<HEAD>\n<LINK href=\"stylesheet.css\" rel=\"stylesheet\" type=\"text/css\">\n<TITLE>" + title + "</TITLE>\n</HEAD>\n\n<BODY>\n\n")

		// begin table
		out.write("<TABLE>\n\n")

		// blog title
		out.write("<TR><TD COLSPAN=3>\n<H1>" + title + "</H1>\n</TD></TR>\n\n")

		// get valid files from folder txt
		val validfs = getValidFiles(new File("txt"))

		for (entry <- orderByTime(validfs)) {

			// dots to separate entries
			out.write("<TR>\n<TD class=nodots></TD>\n<TD class=dots>&nbsp;</TD>\n<TD class=nodots></TD>\n</TR>\n\n")

			// a scanner to read it
			val r = new Scanner(entry)

			// new cell for new entry
			out.write("<TR><TD COLSPAN=3>\n")

			// below: take first line, make it a title
			var line = r.nextLine()
			while (line.length() < 1) {
				line = r.nextLine()
			}
			out.write("<H2>" + replaceScands(line) + "</H2>\n")

			// ready to start new paragraph
			var ps = true

			// Make 1.foo subtitle
			val titlePattern = Pattern.compile("[\\d]+(\\.){1}.*")

			// print non-empty lines, empty lines end paragraph or are skipped
			while (r.hasNextLine()) {
				line = r.nextLine()
				val tpm = titlePattern.matcher(line)

				if (ps && tpm.matches()) {
					out.write("\n<H3>" + tpm.group(0) + "</H3>\n")
				}

				else if (line.length > 0) {	// encountered non-empty line
					if (!ps) {	// A case of "This is\na sentence"
						line = "<BR />" + line
					}
					else {		// new paragraph after empty line
						out.write("<P>")
						ps = false	// not ready to start new paragraph
					}
					out.write(replaceScands(line))
				}
				else {	// empty line
					if (!ps) {	// first encountered empty line after started paragraph: end paragraph
						out.write("</P>\n")
						ps = true	// ready to start new paragraph
					}	// else just empty lines, skip them
				}
			}

			// reached end of file, but paragraph not ended properly?
			if (!ps) out.write("</P>\n")

			// timestamp
			val date = new Date(entry.lastModified())
			out.write("<P class=timestamp>" + DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date) + "</P>\n")

			// close cell
			out.write("</TD></TR>\n\n")

		}

		// end table
		out.write("</TABLE>\n\n")

		// print tail
		out.write("\n\n</BODY>\n</HTML>")

		// remember to close PrintWriter
		out.flush()
		out.close()

	}

}
